ronantakizawa/codereview-bench huggingface dataset:
Repository: withastro/astro
File: packages/integrations/netlify/src/ssr-function.ts (TypeScript)

Code before:
import type { Context } from '@netlify/functions';
import { setGetEnv } from 'astro/env/setup';
import { middlewareSecret, cacheOnDemandPages, packageVersion } from 'virtual:astro-netlify:config';
import { createApp } from 'astro/app/entrypoint';

setGetEnv((key) => process.env[key]);

const app = createApp(import.meta.env.DEV);

export default async function handler(request: Request, context: Context): Promise<Response> {
	const routeData = app.match(request);

	if (!routeData && app.manifest.assets.has('/404.html')) {
		try {
			const body = await fetch(new URL('/404.html', request.url)).then((res) => res.arrayBuffer());
			return new Response(body, {
				status: 404,
				headers: { 'Content-Type': 'text/html; charset=utf-8' },
			});
		} catch {}
	}

	let locals: Record<string, unknown> = {};

	const astroLocalsHeader = request.headers.get('x-astro-locals');
	const middlewareSecretHeader = request.headers.get('x-astro-middleware-secret');
	if (astroLocalsHeader) {
		if (middlewareSecretHeader !== middlewareSecret) {
			return new Response('Forbidden', { status: 403 });
		}
		// hide the secret from the rest of user and library code
		request.headers.delete('x-astro-middleware-secret');
		locals = JSON.parse(astroLocalsHeader);
	}

	locals.netlify = { context };

	const response = await app.render(request, {
		routeData,
		locals,

Review comment (security):
I don't know if we can trust `request.url` here, if the `Host` header is not sanitized (not sure if Netlify does this or not) then an attacker could do bad things. I think we should avoid `fetch`. I can't tell how the old code worked.

Code after:
import type { Context } from '@netlify/functions';
import { setGetEnv } from 'astro/env/setup';
import { middlewareSecret, cacheOnDemandPages, packageVersion } from 'virtual:astro-netlify:config';
import { createApp } from 'astro/app/entrypoint';

setGetEnv((key) => process.env[key]);

const app = createApp();

export function createHandler({ notFoundContent }: { notFoundContent: string | undefined }) {
	return async function handler(request: Request, context: Context): Promise<Response> {
		const routeData = app.match(request);

		if (!routeData && typeof notFoundContent !== 'undefined') {
			return new Response(notFoundContent, {
				status: 404,
				headers: { 'Content-Type': 'text/html; charset=utf-8' },
			});
		}

		let locals: Record<string, unknown> = {};

		const astroLocalsHeader = request.headers.get('x-astro-locals');
		const middlewareSecretHeader = request.headers.get('x-astro-middleware-secret');
		if (astroLocalsHeader) {
			if (middlewareSecretHeader !== middlewareSecret) {
				return new Response('Forbidden', { status: 403 });
			}
			// hide the secret from the rest of user and library code
			request.headers.delete('x-astro-middleware-secret');
			locals = JSON.parse(astroLocalsHeader);
		}

		locals.netlify = { context };

		const response = await app.render(request, {
			routeData,
			locals,
			clientAddress: context.ip,
		});
Repository: withastro/astro
File: packages/astro/src/types/public/config.ts (TypeScript)

Code before:
		 *     allowedDomains: [
		 *       {
		 *         hostname: '**.example.com',
		 *         protocol: 'https'
		 *       },
		 *       {
		 *         hostname: 'staging.myapp.com',
		 *         protocol: 'https',
		 *         port: '443'
		 *       }
		 *     ]
		 *   }
		 * }
		 * ```
		 *
		 * When not configured, `X-Forwarded-Host` headers are not trusted and will be ignored.
		 */
		allowedDomains?: Partial<RemotePattern>[];

		/**
		 * @docs
		 * @name security.actionBodySizeLimit
		 * @kind h4
		 * @type {number}
		 * @default `1048576` (1 MB)
		 * @version 5.x.0
		 * @description
		 *
		 * Sets the maximum size in bytes allowed for action request bodies.
		 *
		 * By default, action request bodies are limited to 1 MB (1048576 bytes) to prevent abuse.
		 * You can increase this limit if your actions need to accept larger payloads, for example when handling file uploads.
		 *
		 * ```js
		 * // astro.config.mjs
		 * export default defineConfig({
		 *   security: {
		 *     actionBodySizeLimit: 10 * 1024 * 1024 // 10 MB
		 *   }
		 * })
		 * ```
		 */
		actionBodySizeLimit?: number;

		/**
		 * @docs
		 * @name security.csp
		 * @kind h4
		 * @type {boolean | object}
		 * @default `false`
		 * @version 6.0.0

Review comment (suggestion):
Docs wise, LGTM! But we need to update [the version](https://github.com/withastro/astro/blob/efae11cef1ebe1f2f54ceb55db0d1ff1938351c6/packages/astro/src/types/public/config.ts#L643C15-L643C21):
```suggestion
		 * @version 5.18.0
```

Code after:
		 *     allowedDomains: [
		 *       {
		 *         hostname: '**.example.com',
		 *         protocol: 'https'
		 *       },
		 *       {
		 *         hostname: 'staging.myapp.com',
		 *         protocol: 'https',
		 *         port: '443'
		 *       }
		 *     ]
		 *   }
		 * }
		 * ```
		 *
		 * When not configured, `X-Forwarded-Host` headers are not trusted and will be ignored.
		 */
		allowedDomains?: Partial<RemotePattern>[];

		/**
		 * @docs
		 * @name security.actionBodySizeLimit
		 * @kind h4
		 * @type {number}
		 * @default `1048576` (1 MB)
		 * @version 5.18.0
		 * @description
		 *
		 * Sets the maximum size in bytes allowed for action request bodies.
		 *
		 * By default, action request bodies are limited to 1 MB (1048576 bytes) to prevent abuse.
		 * You can increase this limit if your actions need to accept larger payloads, for example when handling file uploads.
		 *
		 * ```js
		 * // astro.config.mjs
		 * export default defineConfig({
		 *   security: {
		 *     actionBodySizeLimit: 10 * 1024 * 1024 // 10 MB
		 *   }
		 * })
		 * ```
		 */
		actionBodySizeLimit?: number;

		/**
		 * @docs
		 * @name security.csp
		 * @kind h4
		 * @type {boolean | object}
		 * @default `false`
		 * @version 6.0.0
Repository: withastro/astro
File: packages/astro/src/transitions/cssesc.ts (TypeScript)

Code before:
/* eslint-disable regexp/control-character-escape */
/* eslint-disable no-control-regex */
/* eslint-disable regexp/no-optional-assertion */
/* eslint-disable regexp/no-useless-escape */
/* eslint-disable regexp/no-obscure-range */
// ESM vendored version of cssesc: https://github.com/mathiasbynens/cssesc/blob/cb894eb42f27c8d3cd793f16afe35b3ab38000a1/cssesc.js

const regexAnySingleEscape = /[ -,\.\/:-@\[-\^`\{-~]/;
const regexSingleEscape = /[ -,\.\/:-@\[\]\^`\{-~]/;
const regexExcessiveSpaces = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g;

interface Options {
	escapeEverything: boolean;
	isIdentifier: boolean;
	quotes: 'single' | 'double';
	wrap: boolean;
}

const DEFAULT_OPTIONS: Options = {
	escapeEverything: false,
	isIdentifier: false,
	quotes: 'single',
	wrap: false,
};

export default function cssesc(string: string, options: Partial<Options> = {}) {
	options = { ...DEFAULT_OPTIONS, ...options };
	const quote = options.quotes === 'double' ? '"' : "'";
	const { isIdentifier } = options;

	const firstChar = string.charAt(0);

Review comment (suggestion):
```suggestion
// ESM vendored version of cssesc: https://github.com/mathiasbynens/cssesc/blob/cb894eb42f27c8d3cd793f16afe35b3ab38000a1/cssesc.js
// See https://github.com/withastro/astro/pull/15669
```

Code after:
/* eslint-disable regexp/control-character-escape */
/* eslint-disable no-control-regex */
/* eslint-disable regexp/no-optional-assertion */
/* eslint-disable regexp/no-useless-escape */
/* eslint-disable regexp/no-obscure-range */
// ESM vendored version of cssesc: https://github.com/mathiasbynens/cssesc/blob/cb894eb42f27c8d3cd793f16afe35b3ab38000a1/cssesc.js
// See https://github.com/withastro/astro/pull/15669

const regexAnySingleEscape = /[ -,\.\/:-@\[-\^`\{-~]/;
const regexSingleEscape = /[ -,\.\/:-@\[\]\^`\{-~]/;
const regexExcessiveSpaces = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g;

interface Options {
	escapeEverything: boolean;
	isIdentifier: boolean;
	quotes: 'single' | 'double';
	wrap: boolean;
}

const DEFAULT_OPTIONS: Options = {
	escapeEverything: false,
	isIdentifier: false,
	quotes: 'single',
	wrap: false,
};

export default function cssesc(string: string, options: Partial<Options> = {}) {
	options = { ...DEFAULT_OPTIONS, ...options };
	const quote = options.quotes === 'double' ? '"' : "'";
	const { isIdentifier } = options;
Repository: wolfpld/tracy
File: client/TracyProfiler.cpp (C++)

Code before:
#  include <sys/time.h>
#  include <sys/param.h>
#endif

#ifdef __CYGWIN__
#  include <windows.h>
#  include <unistd.h>
#  include <tlhelp32.h>
#endif

#ifdef _GNU_SOURCE
#  include <errno.h>
#endif

#ifdef __linux__
#  include <dirent.h>
#  include <signal.h>
#  include <pthread.h>
#  include <sys/types.h>
#  include <sys/syscall.h>
#endif

#ifdef __ANDROID__
#  include <sys/mman.h>
#  include <cstdio>
#  include <cstdint>
#  include <vector>
#  include <mutex>
#endif

#if defined __APPLE__ || defined BSD
#  include <sys/types.h>
#  include <sys/sysctl.h>
#endif

#if defined __APPLE__
#  include "TargetConditionals.h"
#endif

#include <algorithm>
#include <assert.h>
#include <atomic>
#include <chrono>
#include <limits>
#include <new>
#include <stdlib.h>
#include <string.h>
#include <thread>

#include "../common/TracyAlign.hpp"
#include "../common/TracySocket.hpp"

Review comment (suggestion):
Use C headers (e.g. `stdio.h`) and `std::`-less types.

Code after:
#  include <sys/time.h>
#  include <sys/param.h>
#endif

#ifdef __CYGWIN__
#  include <windows.h>
#  include <unistd.h>
#  include <tlhelp32.h>
#endif

#ifdef _GNU_SOURCE
#  include <errno.h>
#endif

#ifdef __linux__
#  include <dirent.h>
#  include <signal.h>
#  include <pthread.h>
#  include <sys/types.h>
#  include <sys/syscall.h>
#endif

#if defined __APPLE__ || defined BSD
#  include <sys/types.h>
#  include <sys/sysctl.h>
#endif

#if defined __APPLE__
#  include "TargetConditionals.h"
#endif

#ifdef __ANDROID__
#  include <sys/mman.h>
#  include <stdio.h>
#  include <stdint.h>
#  include <algorithm>
#  include <vector>
#endif

#include <algorithm>
#include <assert.h>
#include <atomic>
#include <chrono>
#include <limits>
#include <new>
#include <stdlib.h>
#include <string.h>
#include <thread>

#include "../common/TracyAlign.hpp"
#include "../common/TracySocket.hpp"
Repository: wolfpld/tracy
File: TracyOpenGL.hpp (C++)

Code before:
    void SyncClockAndSendContextInfo()
    {
        ZoneScopedC( Color::Red4 );

        int64_t tgpu;
        glGetInteger64v( GL_TIMESTAMP, &tgpu );
        int64_t tcpu = Profiler::GetTime();

        GLint bits;
        glGetQueryiv( GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, &bits );

        const float period = 1.f;
        const auto thread = GetThreadHandle();

        TracyLfqPrepare(QueueType::GpuNewContext);
        MemWrite( &item->gpuNewContext.cpuTime, tcpu );
        MemWrite( &item->gpuNewContext.gpuTime, tgpu );
        MemWrite( &item->gpuNewContext.thread, thread );
        MemWrite( &item->gpuNewContext.period, period );
        MemWrite( &item->gpuNewContext.context, m_context );
        MemWrite( &item->gpuNewContext.flags, uint8_t(0) );
        MemWrite( &item->gpuNewContext.type, GpuContextType::OpenGl );

#if defined( TRACY_ON_DEMAND )
        GetProfiler().DeferItem( *item );
#elif defined( TRACY_ON_DEMAND_GPU_SYNC )
        m_isContextReady = true;
#endif

        TracyLfqCommit;
    }

    tracy_force_inline unsigned int NextQueryId()
    {
        const auto id = m_head;
        m_head = ( m_head + 1 ) % QueryCount;
        assert( m_head != m_tail );
        return id;
    }

    tracy_force_inline unsigned int TranslateOpenGlQueryId( unsigned int id )
    {
        return m_query[id];
    }

    tracy_force_inline uint8_t GetId() const
    {
        return m_context;
    }

#ifdef TRACY_ON_DEMAND_GPU_SYNC

Review comment (suggestion):
Is the condition order here the way you intended to be? `TRACY_ON_DEMAND_GPU_SYNC` does not make sense without `TRACY_ON_DEMAND`.

Code after:
    void SyncClockAndSendContextInfo()
    {
        ZoneScopedC( Color::Red4 );

        int64_t tgpu;
        glGetInteger64v( GL_TIMESTAMP, &tgpu );
        int64_t tcpu = Profiler::GetTime();

        GLint bits;
        glGetQueryiv( GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, &bits );

        const float period = 1.f;
        const auto thread = GetThreadHandle();

        TracyLfqPrepare(QueueType::GpuNewContext);
        MemWrite( &item->gpuNewContext.cpuTime, tcpu );
        MemWrite( &item->gpuNewContext.gpuTime, tgpu );
        MemWrite( &item->gpuNewContext.thread, thread );
        MemWrite( &item->gpuNewContext.period, period );
        MemWrite( &item->gpuNewContext.context, m_context );
        MemWrite( &item->gpuNewContext.flags, uint8_t(0) );
        MemWrite( &item->gpuNewContext.type, GpuContextType::OpenGl );

#ifdef TRACY_ON_DEMAND
#ifdef TRACY_ON_DEMAND_GPU_SYNC
        m_isContextReady = true;
#else
        GetProfiler().DeferItem( *item );
#endif
#endif

        TracyLfqCommit;
    }

    tracy_force_inline unsigned int NextQueryId()
    {
        const auto id = m_head;
        m_head = ( m_head + 1 ) % QueryCount;
        assert( m_head != m_tail );
        return id;
    }

    tracy_force_inline unsigned int TranslateOpenGlQueryId( unsigned int id )
    {
        return m_query[id];
    }

    tracy_force_inline uint8_t GetId() const
    {
        return m_context;
    }
Repository: wolfpld/tracy
File: TracyOpenCL.hpp (C++)

Code before:
#ifndef __TRACYOPENCL_HPP__
#define __TRACYOPENCL_HPP__

#if !defined TRACY_ENABLE

#define TracyCLContext(c, x) nullptr
#define TracyCLDestroy(c)
#define TracyCLContextName(c, x, y)

#define TracyCLNamedZone(c, x, y, z)
#define TracyCLNamedZoneC(c, x, y, z, w)
#define TracyCLZone(c, x)
#define TracyCLZoneC(c, x, y)

#define TracyCLNamedZoneS(c, x, y, z, w)
#define TracyCLNamedZoneCS(c, x, y, z, w, v)
#define TracyCLZoneS(c, x, y)
#define TracyCLZoneCS(c, x, y, z)

#define TracyCLNamedZoneSetEvent(x, e)
#define TracyCLZoneSetEvent(e)

#define TracyCLCollect(c)
#define TracyCLBlockingCollect(c)

namespace tracy
{
    class OpenCLCtxScope {};
}

using TracyCLCtx = void*;

#else

#include <CL/cl.h>

#include <atomic>
#include <cassert>
#include <sstream>

#include "Tracy.hpp"
#include "client/TracyCallstack.hpp"
#include "client/TracyProfiler.hpp"
#include "common/TracyAlloc.hpp"

#define TRACY_CL_TO_STRING_INDIRECT(T) #T
#define TRACY_CL_TO_STRING(T) TRACY_CL_TO_STRING_INDIRECT(T)
#define TRACY_CL_ASSERT(p) if(!(p)) {                                                         \
    TracyMessageL( "TRACY_CL_ASSERT failed on " __FILE__ ":" TRACY_CL_TO_STRING(__LINE__) );  \

Review comment (suggestion):
Unfortunately I don't think this should be provided as an option. It should be the user's responsibility to ensure that all events are finished before a call to `TracyCLCollect`. I understand your reasoning but the profiler should not block.

If the user launches an async operation it shouldn't be the profiler responsibility to wait for it.

Code after:
#ifndef __TRACYOPENCL_HPP__
#define __TRACYOPENCL_HPP__

#if !defined TRACY_ENABLE

#define TracyCLContext(c, x) nullptr
#define TracyCLDestroy(c)
#define TracyCLContextName(c, x, y)

#define TracyCLNamedZone(c, x, y, z)
#define TracyCLNamedZoneC(c, x, y, z, w)
#define TracyCLZone(c, x)
#define TracyCLZoneC(c, x, y)

#define TracyCLNamedZoneS(c, x, y, z, w)
#define TracyCLNamedZoneCS(c, x, y, z, w, v)
#define TracyCLZoneS(c, x, y)
#define TracyCLZoneCS(c, x, y, z)

#define TracyCLNamedZoneSetEvent(x, e)
#define TracyCLZoneSetEvent(e)

#define TracyCLCollect(c)

namespace tracy
{
    class OpenCLCtxScope {};
}

using TracyCLCtx = void*;

#else

#include <CL/cl.h>

#include <atomic>
#include <cassert>
#include <sstream>

#include "Tracy.hpp"
#include "client/TracyCallstack.hpp"
#include "client/TracyProfiler.hpp"
#include "common/TracyAlloc.hpp"

#define TRACY_CL_TO_STRING_INDIRECT(T) #T
#define TRACY_CL_TO_STRING(T) TRACY_CL_TO_STRING_INDIRECT(T)
#define TRACY_CL_ASSERT(p) if(!(p)) {                                                         \
    TracyMessageL( "TRACY_CL_ASSERT failed on " __FILE__ ":" TRACY_CL_TO_STRING(__LINE__) );  \
    assert(false && "TRACY_CL_ASSERT failed");                                                \
Repository: wolfpld/tracy
File: server/TracyPrint.cpp (C++)

Code before:
    }
}

static inline void PrintSecondsFrac( char*& buf, uint64_t v )
{
    uint64_t in = v / 1000;
    uint64_t fr = v % 1000;
    if( fr >= 950 )
    {
        PrintTinyInt0( buf, in+1 );
    }
    else
    {
        PrintTinyInt0( buf, in );
        if( fr > 50 )
        {
            PrintFrac0( buf, fr );
        }
    }
}

uint64_t _int64_abs( int64_t x )
{
    if( x == std::numeric_limits<int64_t>::min() )
    {
        return -(x + 1) + 1;
    }
    else if( x < 0 )
    {
        return -x;
    }
    else
    {
        return x;
    }
}

const char* TimeToString( int64_t _ns )
{
    enum { Pool = 8 };
    static char bufpool[Pool][64];
    static int bufsel = 0;
    char* buf = bufpool[bufsel];
    char* bufstart = buf;
    bufsel = ( bufsel + 1 ) % Pool;

    uint64_t ns = _int64_abs(_ns);
    if( _ns < 0 )
    {
        *buf = '-';
        buf++;

Review comment (suggestion):
Shouldn't this be casted to uint64_t before adding 1?
Example with int8_t so it's readable:
```
int8_t x  == -128
=> (x+1)  == -127
=> -(x+1) == 127 // ok, fits into int8_t
=> -(x+1) + 1 == ??? // still a signed int8_t, right?
                    // as 128 doesn't fit into int8_t, it probably wraps around to -128

=> should be `uint64_t(-(x + 1)) + 1;`
```

However, https://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs claims that that for **every _negative_ x** the following works (so you don't need the INT64_MIN special case):
```c++
return -(uint64_t)x;
```
They write (using `unsigned` and `int` instead of (u)int64_t):
> But citing the ISO C99 spec on July 9, 2008, Vincent Lefèvre convinced me to remove it becasue even on non-2s-complement machines -(unsigned)v will do the right thing.
> The evaluation of `-(unsigned)v` first converts the negative value of `v` to an unsigned by adding `2**N`, yielding a 2s complement representation of v's value that I'll call U. Then, U is negated, giving the desired result,
> `-U = 0 - U = 2**N - U = 2**N - (v+2**N) = -v = abs(v)`. 

Code after:
    }
}

static inline void PrintSecondsFrac( char*& buf, uint64_t v )
{
    uint64_t in = v / 1000;
    uint64_t fr = v % 1000;
    if( fr >= 950 )
    {
        PrintTinyInt0( buf, in+1 );
    }
    else
    {
        PrintTinyInt0( buf, in );
        if( fr > 50 )
        {
            PrintFrac0( buf, fr );
        }
    }
}

uint64_t _int64_abs( int64_t x )
{
    if( x < 0 )
    {
        // `-x` does not work if `x` is `std::numeric_limits<int64_t>::min()`,
        // see https://github.com/wolfpld/tracy/pull/1040
        // This works though:
        // https://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
        return -(uint64_t)x;
    }
    else
    {
        return x;
    }
}

const char* TimeToString( int64_t _ns )
{
    enum { Pool = 8 };
    static char bufpool[Pool][64];
    static int bufsel = 0;
    char* buf = bufpool[bufsel];
    char* bufstart = buf;
    bufsel = ( bufsel + 1 ) % Pool;

    uint64_t ns = _int64_abs(_ns);
    if( _ns < 0 )
    {
        *buf = '-';
        buf++;
Repository: woltapp/blurhash
File: Kotlin/lib/src/main/java/com/wolt/blurhashkt/BlurHashDecoder.kt (Kotlin)

Code before:
    private fun decodeDc(value: Int): Array<Float> {
        val intR = value shr 16
        val intG = (value shr 8) and 255
        val intB = value and 255
        return arrayOf(sRgbToLinear(intR), sRgbToLinear(intG), sRgbToLinear(intB))
    }

    private fun sRgbToLinear(value: Int): Float {
        val v = value / 255f
        return if (v <= 0.04045) (v / 12.92f) else ((v + 0.055) / 1.055).pow(2.4).toFloat()
    }

    private fun decodeAc(value: Int, maximumValue: Float): Array<Float> {
        val quantR = value / (19 * 19)
        val quantG = (value / 19) % 19
        val quantB = value % 19
        return arrayOf(
                signPow((quantR - 9) / 9.0f, 2.0f) * maximumValue,
                signPow((quantG - 9) / 9.0f, 2.0f) * maximumValue,
                signPow((quantB - 9) / 9.0f, 2.0f) * maximumValue
        )
    }

    private fun signPow(value: Float, exp: Float) = value.pow(exp).withSign(value)

    private fun linearToSRgb(value: Float): Int {
        val v = value.coerceIn(0f, 1f)
        return if (v <= 0.0031308f) {
            (v * 12.92f * 255 + 0.5f).toInt()
        } else {
            ((1.055f * v.toDouble().pow( 1 / 2.4) - 0.055f) * 255 + 0.5f).toInt()
        }
    }

}


Review comment (suggestion):
`abs()` is not needed. Yes, the sign may be different after the `pow`, but `withSign` (Kotlin for `copySign`) changes it again anyway.

Code after:
    }

    private fun decodeDc(value: Int): Array<Float> {
        val intR = value shr 16
        val intG = (value shr 8) and 255
        val intB = value and 255
        return arrayOf(sRgbToLinear(intR), sRgbToLinear(intG), sRgbToLinear(intB))
    }

    private fun sRgbToLinear(value: Int): Float {
        val v = value / 255f
        return if (v <= 0.04045) (v / 12.92f) else ((v + 0.055) / 1.055).pow(2.4).toFloat()
    }

    private fun decodeAc(value: Int, maximumValue: Float): Array<Float> {
        val quantR = value / (19 * 19)
        val quantG = (value / 19) % 19
        val quantB = value % 19
        return arrayOf(
                signPow((quantR - 9) / 9.0f, 2.0f) * maximumValue,
                signPow((quantG - 9) / 9.0f, 2.0f) * maximumValue,
                signPow((quantB - 9) / 9.0f, 2.0f) * maximumValue
        )
    }

    private fun signPow(value: Float, exp: Float) = value.pow(exp).withSign(value)

    private fun linearToSRgb(value: Float): Int {
        val v = value.coerceIn(0f, 1f)
        return if (v <= 0.0031308f) {
            (v * 12.92f * 255 + 0.5f).toInt()
        } else {
            ((1.055f * v.toDouble().pow( 1 / 2.4) - 0.055f) * 255 + 0.5f).toInt()
        }
    }

}